package com.epam.training.concurrency.first.task3;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 
 * @author Bogdan
 *
 */
public class CircularBuffer {

	private Integer data[];

	private int head;
	private int tail;

	/**
	 * Main constructor
	 * 
	 * @param size
	 */
	CircularBuffer(int size) {
		data = new Integer[size];
		head = 0;
		tail = 0;
	}

	/**
	 * 
	 * @param value
	 */
	public synchronized void store(Integer value) {
		while (bufferFull()) {
			try {
				wait();
			} catch (InterruptedException e) {
				Logger.getLogger(CircularBuffer.class.getName()).log(
						Level.SEVERE, null, e);
			}
		}

		data[tail++] = value;
		if (tail == data.length) {
			tail = 0;
		}

		notifyAll();
	}

	/**
	 * 
	 * @return
	 */
	public synchronized Integer read() {
		while (bufferEmpty()) {
			try {
				wait();
			} catch (InterruptedException e) {
				Logger.getLogger(CircularBuffer.class.getName()).log(
						Level.SEVERE, null, e);
			}
		}

		int value = data[head++];
		if (head == data.length) {
			head = 0;
		}

		notifyAll();
		return value;
	}

	/**
	 * 
	 * @return true if buffer full
	 */
	private boolean bufferFull() {
		return (tail + 1 == head) || (tail == (data.length - 1) && head == 0);
	}

	/**
	 * 
	 * @return true if buffer empty, false if buffer not empty
	 */
	private boolean bufferEmpty() {
		return head == tail;
	}

	/**
	 * 
	 * @return buffer size
	 */
	public int size() {
		return data.length;
	}
}
